package com.pai4j.zwiki.service.agent;

import com.pai4j.zwiki.service.LLMService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.util.io.DisabledOutputStream;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 代码演化历史分析器
 * 
 * 核心功能：
 * 1. 分析Git提交历史，理解代码演化过程
 * 2. 识别频繁修改的文件（热点文件）
 * 3. 分析代码的重构历史
 * 4. 识别代码腐化趋势
 * 5. 提取开发模式和团队协作特点
 * 6. 使用LLM理解变更的业务背景
 *
 * @author pai4j
 * @since 2025-10-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CodeEvolutionAnalyzer {

    private final LLMService llmService;

    /**
     * 分析代码演化历史
     */
    public Map<String, Object> analyzeCodeEvolution(String workspacePath) {
        log.info("开始分析代码演化历史");

        Map<String, Object> evolution = new HashMap<>();

        try {
            Path projectPath = Paths.get(workspacePath);
            File gitDir = new File(projectPath.toFile(), ".git");

            if (!gitDir.exists()) {
                log.warn("项目不是Git仓库，跳过演化分析");
                evolution.put("message", "项目不是Git仓库");
                return evolution;
            }

            // 打开Git仓库
            Repository repository = new FileRepositoryBuilder()
                    .setGitDir(gitDir)
                    .build();

            Git git = new Git(repository);

            // 1. 获取提交历史
            log.info("1. 获取提交历史");
            List<Map<String, Object>> commits = analyzeCommitHistory(git);
            evolution.put("commits", commits);
            evolution.put("totalCommits", commits.size());

            // 2. 分析文件修改频率
            log.info("2. 分析文件修改频率");
            Map<String, Integer> fileChangeFrequency = analyzeFileChangeFrequency(git);
            evolution.put("fileChangeFrequency", fileChangeFrequency);

            // 3. 识别热点文件（修改最频繁的文件）
            log.info("3. 识别热点文件");
            List<Map<String, Object>> hotspots = identifyHotspotFiles(fileChangeFrequency);
            evolution.put("hotspotFiles", hotspots);

            // 4. 分析提交模式
            log.info("4. 分析提交模式");
            Map<String, Object> commitPatterns = analyzeCommitPatterns(commits);
            evolution.put("commitPatterns", commitPatterns);

            // 5. 识别重大重构
            log.info("5. 识别重大重构");
            List<Map<String, Object>> majorRefactorings = identifyMajorRefactorings(git);
            evolution.put("majorRefactorings", majorRefactorings);

            // 6. 使用LLM分析演化趋势
            log.info("6. LLM分析演化趋势");
            String evolutionAnalysis = analyzeEvolutionWithLLM(evolution);
            evolution.put("llmEvolutionAnalysis", evolutionAnalysis);

            git.close();
            repository.close();

            log.info("代码演化历史分析完成");

        } catch (Exception e) {
            log.error("分析代码演化失败", e);
            evolution.put("error", e.getMessage());
        }

        return evolution;
    }

    /**
     * 分析提交历史
     */
    private List<Map<String, Object>> analyzeCommitHistory(Git git) throws GitAPIException {
        List<Map<String, Object>> commits = new ArrayList<>();

        Iterable<RevCommit> logs = git.log().setMaxCount(100).call();

        for (RevCommit commit : logs) {
            Map<String, Object> commitInfo = new HashMap<>();
            commitInfo.put("hash", commit.getName());
            commitInfo.put("author", commit.getAuthorIdent().getName());
            commitInfo.put("email", commit.getAuthorIdent().getEmailAddress());
            commitInfo.put("message", commit.getFullMessage());
            commitInfo.put("timestamp", commit.getCommitTime());
            commitInfo.put("date", LocalDateTime.ofInstant(
                    Instant.ofEpochSecond(commit.getCommitTime()),
                    ZoneId.systemDefault()
            ));

            commits.add(commitInfo);
        }

        return commits;
    }

    /**
     * 分析文件修改频率
     */
    private Map<String, Integer> analyzeFileChangeFrequency(Git git) throws GitAPIException, IOException {
        Map<String, Integer> frequency = new HashMap<>();

        Repository repository = git.getRepository();
        RevWalk walk = new RevWalk(repository);
        ObjectId head = repository.resolve("HEAD");
        
        if (head == null) {
            return frequency;
        }

        Iterable<RevCommit> commits = git.log().setMaxCount(100).call();
        DiffFormatter diffFormatter = new DiffFormatter(DisabledOutputStream.INSTANCE);
        diffFormatter.setRepository(repository);

        RevCommit lastCommit = null;
        for (RevCommit commit : commits) {
            if (lastCommit != null) {
                List<DiffEntry> diffs = diffFormatter.scan(lastCommit.getTree(), commit.getTree());
                for (DiffEntry diff : diffs) {
                    String path = diff.getNewPath();
                    if (path.endsWith(".java")) {
                        frequency.put(path, frequency.getOrDefault(path, 0) + 1);
                    }
                }
            }
            lastCommit = commit;
        }

        walk.close();
        diffFormatter.close();

        return frequency;
    }

    /**
     * 识别热点文件
     */
    private List<Map<String, Object>> identifyHotspotFiles(Map<String, Integer> frequency) {
        return frequency.entrySet().stream()
                .sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()))
                .limit(20)
                .map(entry -> {
                    Map<String, Object> hotspot = new HashMap<>();
                    hotspot.put("filePath", entry.getKey());
                    hotspot.put("changeCount", entry.getValue());
                    hotspot.put("hotspotLevel", getHotspotLevel(entry.getValue()));
                    return hotspot;
                })
                .collect(Collectors.toList());
    }

    /**
     * 分析提交模式
     */
    private Map<String, Object> analyzeCommitPatterns(List<Map<String, Object>> commits) {
        Map<String, Object> patterns = new HashMap<>();

        // 按作者统计
        Map<String, Long> authorCounts = commits.stream()
                .collect(Collectors.groupingBy(
                        c -> (String) c.get("author"),
                        Collectors.counting()
                ));
        patterns.put("authorContributions", authorCounts);

        // 识别提交类型（基于commit message）
        Map<String, Long> commitTypes = commits.stream()
                .collect(Collectors.groupingBy(
                        c -> classifyCommitType((String) c.get("message")),
                        Collectors.counting()
                ));
        patterns.put("commitTypes", commitTypes);

        // 计算平均提交间隔
        if (commits.size() >= 2) {
            List<Long> timestamps = commits.stream()
                    .map(c -> ((Number) c.get("timestamp")).longValue())
                    .sorted()
                    .collect(Collectors.toList());

            long totalInterval = 0;
            for (int i = 1; i < timestamps.size(); i++) {
                totalInterval += timestamps.get(i) - timestamps.get(i - 1);
            }
            long avgInterval = totalInterval / (timestamps.size() - 1);
            patterns.put("averageCommitInterval", avgInterval / 3600 + " 小时");
        }

        return patterns;
    }

    /**
     * 识别重大重构
     */
    private List<Map<String, Object>> identifyMajorRefactorings(Git git) throws GitAPIException, IOException {
        List<Map<String, Object>> refactorings = new ArrayList<>();

        Repository repository = git.getRepository();
        Iterable<RevCommit> commits = git.log().setMaxCount(100).call();
        DiffFormatter diffFormatter = new DiffFormatter(DisabledOutputStream.INSTANCE);
        diffFormatter.setRepository(repository);

        RevCommit lastCommit = null;
        for (RevCommit commit : commits) {
            String message = commit.getFullMessage().toLowerCase();
            
            // 识别重构相关的提交
            if (message.contains("refactor") || message.contains("重构") || 
                message.contains("optimize") || message.contains("优化")) {
                
                if (lastCommit != null) {
                    List<DiffEntry> diffs = diffFormatter.scan(lastCommit.getTree(), commit.getTree());
                    
                    // 如果修改了多个文件，认为是重大重构
                    if (diffs.size() >= 5) {
                        Map<String, Object> refactoring = new HashMap<>();
                        refactoring.put("commitHash", commit.getName());
                        refactoring.put("message", commit.getFullMessage());
                        refactoring.put("author", commit.getAuthorIdent().getName());
                        refactoring.put("filesChanged", diffs.size());
                        refactoring.put("date", LocalDateTime.ofInstant(
                                Instant.ofEpochSecond(commit.getCommitTime()),
                                ZoneId.systemDefault()
                        ));
                        
                        refactorings.add(refactoring);
                    }
                }
            }
            
            lastCommit = commit;
        }

        diffFormatter.close();
        return refactorings;
    }

    /**
     * 使用LLM分析演化趋势
     */
    private String analyzeEvolutionWithLLM(Map<String, Object> evolution) {
        StringBuilder prompt = new StringBuilder();
        prompt.append("请分析以下代码演化历史数据：\n\n");

        // 提交统计
        prompt.append("## 提交历史\n\n");
        prompt.append("- 总提交数：").append(evolution.get("totalCommits")).append("\n");

        // 热点文件
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> hotspots = (List<Map<String, Object>>) evolution.get("hotspotFiles");
        if (hotspots != null && !hotspots.isEmpty()) {
            prompt.append("\n## 热点文件（修改最频繁）\n\n");
            hotspots.stream().limit(10).forEach(h -> {
                prompt.append(String.format("- %s (修改 %d 次) - %s\n",
                        h.get("filePath"), h.get("changeCount"), h.get("hotspotLevel")));
            });
        }

        // 重大重构
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> refactorings = (List<Map<String, Object>>) evolution.get("majorRefactorings");
        if (refactorings != null && !refactorings.isEmpty()) {
            prompt.append("\n## 重大重构记录\n\n");
            refactorings.stream().limit(5).forEach(r -> {
                prompt.append(String.format("- [%s] %s\n", r.get("date"), r.get("message")));
            });
        }

        prompt.append("""
                
                ---
                
                请深入分析：
                
                ## 1. 演化趋势（30%）
                - 从提交历史看，项目处于什么发展阶段？（初期/成长期/成熟期）
                - 代码变更的主要方向是什么？
                - 是在持续改进还是在修复问题？
                
                ## 2. 热点文件分析（25%）
                - 为什么这些文件修改频繁？
                - 频繁修改说明了什么问题？
                - 是业务变化快，还是设计不稳定？
                
                ## 3. 重构活动评估（20%）
                - 重构的频率和力度如何？
                - 重构的方向和目标是什么？
                - 重构是否改善了代码质量？
                
                ## 4. 团队协作特点（15%）
                - 从提交模式看，团队是如何协作的？
                - 代码所有权是否清晰？
                
                ## 5. 技术债务演化（10%）
                - 技术债务是在增加还是减少？
                - 需要注意哪些潜在风险？
                
                请详细分析（1000-1500字）。
                """);

        try {
            return llmService.generateCodeSummary(prompt.toString());
        } catch (Exception e) {
            log.error("LLM分析演化趋势失败", e);
            return "演化分析失败: " + e.getMessage();
        }
    }

    // ========== 辅助方法 ==========

    private String classifyCommitType(String message) {
        String lower = message.toLowerCase();
        
        if (lower.startsWith("feat") || lower.contains("新增") || lower.contains("添加")) {
            return "功能开发";
        }
        if (lower.startsWith("fix") || lower.contains("修复") || lower.contains("bug")) {
            return "Bug修复";
        }
        if (lower.startsWith("refactor") || lower.contains("重构")) {
            return "代码重构";
        }
        if (lower.startsWith("docs") || lower.contains("文档")) {
            return "文档更新";
        }
        if (lower.startsWith("test") || lower.contains("测试")) {
            return "测试相关";
        }
        if (lower.startsWith("perf") || lower.contains("性能") || lower.contains("优化")) {
            return "性能优化";
        }
        
        return "其他";
    }

    private String getHotspotLevel(int changeCount) {
        if (changeCount >= 20) return "🔥 极热";
        if (changeCount >= 10) return "🌡️ 很热";
        if (changeCount >= 5) return "⚠️ 较热";
        return "✅ 正常";
    }
}

